package com.wimcorp.magic.cost;

import java.rmi.RemoteException;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.Transient;

import com.wimcorp.magic.color.Color;
import com.wimcorp.magic.exception.CostException;
import com.wimcorp.magic.mana.Mana;
import com.wimcorp.magic.mana.ManaHolder;
import com.wimcorp.magic.mana.ManaList;
import com.wimcorp.magic.mana.ManaPool;
import com.wimcorp.magic.mana.PlayerManaPool;

@Entity
public class ManaCost extends Cost {

	@Embedded
	private ManaHolder manaHolder = new ManaHolder();

	public ManaCost() {

	}

	public ManaCost(ManaCost cost) {
		super(cost);
		for (ManaList manalist : cost.getAllManaLists()) {
			for (Mana mana : manalist.getMana()) {
				addMana(mana.getColor());
			}
		}

	}

	public ManaCost(Color... colors) {
		for (Color color : colors) {
			addMana(color);
		}
	}

	public int getManaCost(Color c) {
		return getMana(c).size();
	}

	public int getTotalManaCost() {
		int total = 0;
		for (Color c : getColorsInPool()) {
			total += getManaCost(c);
		}
		return total;
	}

	public void payCost() throws CostException{
		try {
			boolean success = false;
			do {
				try {
					getPlayer().getUserInterface().conjureMana(String.format("You need to conjure : %s for %s. ", this.toString(),getCastable().getCastDescription()));
					ManaPool conjuredMana = getPlayer().getPayment().getConjuredMana();
					PlayerManaPool playerManaPool = getPlayer().getPlayerManaPool();
					if (haseEnoughManaToCast(playerManaPool)) {
						if (haseEnoughManaToCast(conjuredMana)) {
							if (getTotalManaCost() == conjuredMana.getAvailableMana(Color.NEUTRAL)) {
								getPlayer().consumeMana();
								success = true;
							} else {
								throw new CostException("You conjured more mana than needed to cast this card");
							}
						} else {
							throw new CostException("You didn't generate enough Mana to cast this card");
						}
					} else {
						throw new CostException("You don't have enough Mana to cast this card");
					}
				} catch (CostException e) {
					getPlayer().getUserInterface().message(e.getMessage());
					boolean tryAgain = getPlayer().getUserInterface().selectBoolean(
							String.format("%s. Would you like to try again? ", e.getMessage()));
					if(!tryAgain){
						throw e;
					}
				}
			} while (!success);
		} catch (RemoteException e) {
			e.printStackTrace();
		}
	}

	public void addMana(Color color) {
		manaHolder.addMana(color);
	}

	public List<Mana> getMana(Color c) {
		return manaHolder.getMana(c);
	}

	public Set<Color> getColorsInPool() {
		return manaHolder.getColorsInPool();
	}

	public String toString() {
		StringBuilder manaCost = new StringBuilder();
		Set<Color> colors = getColorsInPool();
		int i = 0;
		for (Color c : colors) {
			i++;
			manaCost.append(c.getColor() + " : " + getMana(c).size());
			if (i != colors.size()) {
				manaCost.append(",");
			}
		}
		return manaCost.toString();
	}

	private boolean haseEnoughManaToCast(ManaPool manaPool) {
		boolean enoughMana = true;
		Set<Color> colors = getColorsInPool();
		int coloredCost = 0;
		for (Color c : colors) {
			if (c != Color.NEUTRAL) {
				int colorCost = getManaCost(c);
				if (manaPool.getMana(c).size() < colorCost) {
					enoughMana = false;
				}
				coloredCost = +colorCost;
			}
		}
		if (manaPool.getAvailableMana(Color.NEUTRAL) - coloredCost < getManaCost(Color.NEUTRAL)) {
			enoughMana = false;
		}
		return enoughMana;
	}

	public Collection<ManaList> getAllManaLists() {
		return manaHolder.getAllManaLists();
	}

	@Override
	public Cost clone() {
		return new ManaCost(this);
	}


}
